`include "PRV564Config.v"
`include "PRV564Define.v"
// Trap Management Unit for PRV564 processor

module TrapManage(
//---------current privilege and pc, virtual address input---------
    input wire [`XLEN-1:0]  instr_pc, instr_VA, instr_jmpaddr,      //当前指令的pc，访存的virtual address和跳转地址
    input wire [1:0]        instr_priv,
    input wire              instr_jmp,                              //当前指令确实发生了跳转
    input wire              instr_system,
//--------None Maskable interrupt------
    input wire              NMI_EccErr, NMI_PwrLost, NMI_generic,
//--------Interrput input and enable--------------
    input wire              mige, sige,                             //Machine and Supervisior interrupt globally enable
    input wire              mei,  sei,                              //Machine and Supervisior mode external interrupt pending
    input wire              meie, seie,                             //Machine and Supervisior mode external interrupt enable
    input wire              mti,  sti,                              //Machine and Supervisior mode timer interrupt
    input wire              mtie, stie,
    input wire              msi,  ssi,                              //Machine and Supervisior mode software interrupt
    input wire              msie, ssie,
//----------exception input------------
    input wire              ecall, ebreak,                          //environment call and break
    input wire              ill_ins,                                //illeagal instructions
    input wire              InstPageFlt, InstAddrMis, InstAccFlt,
    input wire              LoadPageFlt, LoadAddrMis, LoadAccFlt,
    input wire              StorePageFlt,StoreAddrMis,StoreAccFlt,
//-----------mideleg and medeleg---------------
    input wire [`XLEN-1:0]  csr_mideleg, csr_medeleg,
//----------target mode and exception code-----
    output reg [`XLEN-1:0]  trap_value, trap_cause, trap_pc,
    output reg              trap_s, trap_m, trap_async               //trap target to m mode or s mode, and if the trap is async trap
);
/********************************************************************************************************************
                                            关于异常委托的注意事项
中断（Interrupt）异常（Exception）在RISC-V中均称为Trap，中断委托由mideleg寄存器负责，异常委托由medeleg寄存器负责。
在M模式下运行时，低于M模式的所有中断都会被屏蔽。
在S模式下运行时，M模式的中断是全局打开状态，如果S模式的中断没有被委托给S模式，则也无条件交给M模式处理；如果S模式的一个中断被委托
给了S模式，则根据sie寄存器中的开关情况开决定S模式是否处理该中断。
在U模式下运行时候,S模式和M模式的所有中断都是全局开的状态。

**********************************************************************************************************************/

always@(*)begin
    if(instr_system)begin               //当前指令是个系统指令，不进行任何Trap以免造成奇怪的bug
        trap_m      = 1'b0;
        trap_s      = 1'b0;
        trap_async  = 1'b0;
        trap_cause  = 'h0;
        trap_value  = 'hx;
        trap_pc     = 'hx;
    end
    else begin
    case(instr_priv)
        //------------------------当前指令运行在Machine Mode下时--------------------------------
        `Machine :
        begin
            //--------同步异常有最高的处理优先级--------
            if(InstPageFlt)begin                        //instruction page fault
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_InstrPageFlt;       //指令页面错误
                trap_value  = instr_pc;
                trap_pc     = instr_pc;
            end
            else if(InstAccFlt)begin                    //instruction access fault
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_InstrAccFlt;
                trap_value  = instr_pc;
                trap_pc     = instr_pc;
            end
            else if(ill_ins)begin                       //illegal instruction 
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_illins;
                trap_value  = 'd0;                     //异常时，异常指令编码并未提供，写0
                trap_pc     = instr_pc;
            end
            else if(InstAddrMis)begin                   //instruction address misaligned
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_InstrAddrMis;
                trap_value  = instr_pc;
                trap_pc     = instr_pc;
            end
            else if(ecall)begin                         //Environment call
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_EcallFromM;
                trap_value  = 64'h0;
                trap_pc     = instr_pc;                 //ecall指令时，pc设置为当前地址
            end
            else if(ebreak)begin                        //Environment Break point
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_BreakPoint;
                trap_value  = instr_pc;
                trap_pc     = instr_pc + 'd4;          //ebreak指令时，pc设置为下一条地址
            end
            else if(LoadAddrMis)begin                   //Load address misaligned
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_LoadAddrMis;
                trap_value  = instr_VA;
                trap_pc     = instr_pc;
            end
            else if(StoreAddrMis)begin                  //Store address misaligned
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_StoreAddrMis;
                trap_value  = instr_VA;
                trap_pc     = instr_pc;
            end
            else if(LoadPageFlt)begin                   //Load page fault
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_LoadPageFlt;
                trap_value  = instr_VA;
                trap_pc     = instr_pc;
            end
            else if(StorePageFlt)begin                  //Store page fault
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_StorePageFlt;
                trap_value  = instr_VA;
                trap_pc     = instr_pc;
            end
            else if(LoadAccFlt)begin
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_LoadAccFlt;
                trap_value  = instr_VA;
                trap_pc     = instr_pc;
            end
            else if(StoreAccFlt)begin
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = `exc_StoreAccFlt;
                trap_value  = instr_VA;
                trap_pc     = instr_pc;
            end
            //----------NMI中断具有第二高优先级----------
            else if(NMI_PwrLost)begin                   //NMI power lost
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_PwrLost;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(NMI_EccErr)begin                    //NMI ecc error
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_EccErr;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(NMI_generic)begin                   //NMI for general purpose
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_generic;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            //-----------正常中断优先级最低--------------
            //注：在M模式下运行时，除M以外其他权限级的中断都是无条件关闭的状态
            else if(mige)begin                              //Machine mode interrupt is globally enable
                if(mti & mtie)begin                           //Machine mode timer interrupt
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_m_timer;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                end
                else if(mei & meie)begin                           //Machine mode external interrupt
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_m_exter;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                end
                else if(msi & msie)begin                           //Machine mode software interrupt
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_m_soft;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                end
                else begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = 'dx;
                    trap_value  = 'dx;
                    trap_pc     = 'dx;
                end
            end
            else begin
                trap_m      = 1'b0;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = 'dx;
                trap_value  = 'dx;
                trap_pc     = 'dx;
            end
        end
        //-----------------------------当前指令运行在Supervisor下时--------------------------
        `Supervisior :
        begin
            //--------同步异常有最高的处理优先级--------
            if(InstPageFlt)begin                        //instruction page fault
                if(csr_medeleg[`exc_InstrPageFlt])begin //当前异常被委托给S模式处理
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrPageFlt;       //指令页面错误
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
                else begin                              //当前异常没有被委托，由M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrPageFlt;       //指令页面错误
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
            end
            else if(InstAccFlt)begin                    //instruction access fault
                if(csr_medeleg[`exc_InstrAccFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAccFlt;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAccFlt;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
            end
            else if(ill_ins)begin                       //illegal instruction 
                if(csr_medeleg[`exc_illins])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_illins;
                    trap_value  = 'd0;                     //异常时，异常指令编码并未提供，写0
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_illins;
                    trap_value  = 'd0;                     //异常时，异常指令编码并未提供，写0
                    trap_pc     = instr_pc;
                end
            end
            else if(InstAddrMis)begin                   //instruction address misaligned
                if(csr_medeleg[`exc_InstrAddrMis])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAddrMis;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAddrMis;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
            end
            else if(ecall)begin                         //Environment call
                if(csr_medeleg[`exc_EcallFromS])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_EcallFromS;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ecall指令时，pc设置为下一条地址
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_EcallFromS;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ecall指令时，pc设置为下一条地址
                end
            end
            else if(ebreak)begin                        //Environment Break point
                if(csr_medeleg[`exc_BreakPoint])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_BreakPoint;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ebreak指令时，pc设置为下一条地址
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_BreakPoint;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ebreak指令时，pc设置为下一条地址
                end
            end
            else if(LoadAddrMis)begin                   //Load address misaligned
                if(csr_medeleg[`exc_LoadAddrMis])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(StoreAddrMis)begin                  //Store address misaligned
                if(csr_medeleg[`exc_StoreAddrMis])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(LoadPageFlt)begin                   //Load page fault
                if(csr_medeleg[`exc_LoadPageFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadPageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadPageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(StorePageFlt)begin                  //Store page fault
                if(csr_medeleg[`exc_StorePageFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StorePageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StorePageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(LoadAccFlt)begin                  //Store page fault
                if(csr_medeleg[`exc_LoadAccFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(StoreAccFlt)begin                  //Store page fault
                if(csr_medeleg[`exc_StoreAccFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            //----------NMI中断具有第二高优先级----------
            //注：NMI中断不被委托，直接交给固件处理
            else if(NMI_PwrLost)begin                   //NMI power lost
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_PwrLost;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(NMI_EccErr)begin                    //NMI ecc error
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_EccErr;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(NMI_generic)begin                   //NMI for general purpose
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_generic;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            //-----------正常中断优先级最低--------------
            //注：在S模式运行下时，M模式的所有中断都是默认打开的
            else if(mti)begin                           //Machine mode timer interrupt
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `int_m_timer;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(mei)begin                           //Machine mode external interrupt
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `int_m_exter;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(msi)begin                           //Machine mode software interrupt
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `int_m_soft;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(sti)begin                           //Supervisior mode timer interrupt
                if(csr_mideleg[`int_s_timer])begin          //当前中断被委托给S模式，处理与否看S模式心情
                    if(stie & sige)begin
                        trap_m      = 1'b0;
                        trap_s      = 1'b1;
                        trap_async  = 1'b1;
                        trap_cause  = `int_s_timer;
                        trap_value  = 'd0;
                        trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                    end
                    else begin
                        trap_m      = 1'b0;
                        trap_s      = 1'b0;
                        trap_async  = 1'b0;
                        trap_cause  = 'dx;
                        trap_value  = 'dx;
                        trap_pc     = 'dx;
                    end
                end
                else begin                              //当前中断没有被委托，无条件交给M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_timer;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4); 
                end
            end
            else if(sei)begin                           //Supervisior mode external interrupt
                if(csr_mideleg[`int_s_exter])begin          //当前中断被委托给S模式，处理与否看S模式心情
                    if(stie & sige)begin
                        trap_m      = 1'b0;
                        trap_s      = 1'b1;
                        trap_async  = 1'b1;
                        trap_cause  = `int_s_exter;
                        trap_value  = 'd0;
                        trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                    end
                    else begin
                        trap_m      = 1'b0;
                        trap_s      = 1'b0;
                        trap_async  = 1'b0;
                        trap_cause  = 'dx;
                        trap_value  = 'dx;
                        trap_pc     = 'dx;
                    end
                end
                else begin                              //当前中断没有被委托，无条件交给M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_exter;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4); 
                end
            end
            else if(ssi)begin                           //Supervisior mode software interrupt
                if(csr_mideleg[`int_s_soft])begin           //当前中断被委托给S模式，处理与否看S模式心情
                    if(stie & sige)begin
                        trap_m      = 1'b0;
                        trap_s      = 1'b1;
                        trap_async  = 1'b1;
                        trap_cause  = `int_s_soft;
                        trap_value  = 'd0;
                        trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                    end
                    else begin
                        trap_m      = 1'b0;
                        trap_s      = 1'b0;
                        trap_async  = 1'b0;
                        trap_cause  = 'dx;
                        trap_value  = 'dx;
                        trap_pc     = 'dx;
                    end
                end
                else begin                              //当前中断没有被委托，无条件交给M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_soft;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4); 
                end
            end
            else begin
                trap_m      = 1'b0;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = 'dx;
                trap_value  = 'dx;
                trap_pc     = 'dx;
            end
        end
        //---------------------User模式下工作时，所有中断都默认开----------------------
        `User :
        begin
            //--------同步异常有最高的处理优先级--------
            if(InstPageFlt)begin                        //instruction page fault
                if(csr_medeleg[`exc_InstrPageFlt])begin //当前异常被委托给S模式处理
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrPageFlt;       //指令页面错误
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
                else begin                              //当前异常没有被委托，由M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrPageFlt;       //指令页面错误
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
            end
            else if(InstAccFlt)begin                    //instruction access fault
                if(csr_medeleg[`exc_InstrAccFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAccFlt;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAccFlt;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
            end
            else if(ill_ins)begin                       //illegal instruction 
                if(csr_medeleg[`exc_illins])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_illins;
                    trap_value  = 'd0;                     //异常时，异常指令编码并未提供，写0
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_illins;
                    trap_value  = 'd0;                     //异常时，异常指令编码并未提供，写0
                    trap_pc     = instr_pc;
                end
            end
            else if(InstAddrMis)begin                   //instruction address misaligned
                if(csr_medeleg[`exc_InstrAddrMis])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAddrMis;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_InstrAddrMis;
                    trap_value  = instr_pc;
                    trap_pc     = instr_pc;
                end
            end
            else if(ecall)begin                         //Environment call
                if(csr_medeleg[`exc_EcallFromS])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_EcallFromS;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ecall指令时，pc设置为下一条地址
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_EcallFromS;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ecall指令时，pc设置为下一条地址
                end
            end
            else if(ebreak)begin                        //Environment Break point
                if(csr_medeleg[`exc_BreakPoint])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_BreakPoint;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ebreak指令时，pc设置为下一条地址
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_BreakPoint;
                    trap_value  = instr_pc;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);          //ebreak指令时，pc设置为下一条地址
                end
            end
            else if(LoadAddrMis)begin                   //Load address misaligned
                if(csr_medeleg[`exc_LoadAddrMis])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(StoreAddrMis)begin                  //Store address misaligned
                if(csr_medeleg[`exc_StoreAddrMis])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAddrMis;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(LoadPageFlt)begin                   //Load page fault
                if(csr_medeleg[`exc_LoadPageFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadPageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadPageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(StorePageFlt)begin                  //Store page fault
                if(csr_medeleg[`exc_StorePageFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StorePageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StorePageFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(LoadAccFlt)begin                  //Store page fault
                if(csr_medeleg[`exc_LoadAccFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_LoadAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            else if(StoreAccFlt)begin                  //Store page fault
                if(csr_medeleg[`exc_StoreAccFlt])begin
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
                else begin
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b0;
                    trap_cause  = `exc_StoreAccFlt;
                    trap_value  = instr_VA;
                    trap_pc     = instr_pc;
                end
            end
            //----------NMI中断具有第二高优先级----------
            //注：NMI中断不被委托，直接交给固件处理
            else if(NMI_PwrLost)begin                   //NMI power lost
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_PwrLost;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(NMI_EccErr)begin                    //NMI ecc error
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_EccErr;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(NMI_generic)begin                   //NMI for general purpose
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `nmi_generic;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            //-----------正常中断优先级最低--------------
            //注：在U模式运行下时，M模式的所有中断都是默认打开的
            else if(mti)begin                           //Machine mode timer interrupt
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `int_m_timer;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(mei)begin                           //Machine mode external interrupt
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `int_m_exter;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(msi)begin                           //Machine mode software interrupt
                trap_m      = 1'b1;
                trap_s      = 1'b0;
                trap_async  = 1'b1;
                trap_cause  = `int_m_soft;
                trap_value  = 'd0;
                trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
            end
            else if(sti)begin                           //Supervisior mode timer interrupt
                if(csr_mideleg[`int_s_timer])begin          //当前中断被委托给S模式，且全局打开
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_timer;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                end
                else begin                              //当前中断没有被委托，无条件交给M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_timer;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4); 
                end
            end
            else if(sei)begin                           //Supervisior mode external interrupt
                if(csr_mideleg[`int_s_exter])begin          //当前中断被委托给S模式，且全局开
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_exter;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                end
                else begin                              //当前中断没有被委托，无条件交给M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_exter;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4); 
                end
            end
            else if(ssi)begin                           //Supervisior mode software interrupt
                if(csr_mideleg[`int_s_soft])begin           //当前中断被委托给S模式，且全局打开
                    trap_m      = 1'b0;
                    trap_s      = 1'b1;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_soft;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4);
                end
                else begin                              //当前中断没有被委托，无条件交给M模式处理
                    trap_m      = 1'b1;
                    trap_s      = 1'b0;
                    trap_async  = 1'b1;
                    trap_cause  = `int_s_soft;
                    trap_value  = 'd0;
                    trap_pc     = instr_jmp ? instr_jmpaddr : (instr_pc + 'd4); 
                end
            end
            else begin
                trap_m      = 1'b0;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = 'dx;
                trap_value  = 'dx;
                trap_pc     = 'dx;
            end
        end
        default:
        begin
                trap_m      = 1'b0;
                trap_s      = 1'b0;
                trap_async  = 1'b0;
                trap_cause  = 'dx;
                trap_value  = 'dx;
                trap_pc     = 'dx;
        end
    endcase
    end
end

endmodule
